package com.mzj.saas.rent;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.gson.reflect.TypeToken;
import com.haixiaoke.saas.repository.core.AjaxResult;
import com.haixiaoke.saas.repository.core.BaseController;
import com.haixiaoke.saas.repository.core.page.TableDataInfo;
import com.haixiaoke.saas.repository.dto.*;
import com.haixiaoke.saas.repository.exception.BizException;
import com.haixiaoke.saas.repository.pojo.*;
import com.haixiaoke.saas.repository.service.*;
import com.haixiaoke.saas.repository.util.GsonUtil;
import com.haixiaoke.saas.repository.util.PlaceholderUtil;
import com.haixiaoke.saas.repository.vo.OrderAmountVO;
import com.mzj.saas.annotation.CheckAuth;
import com.mzj.saas.annotation.RepeatSubmit;
import com.mzj.saas.commons.Constant;
import com.mzj.saas.commons.StatusCode;
import com.mzj.saas.commons.enums.PaymentTypeEnum;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.config.pay.PayConfig;
import com.mzj.saas.config.sms.SmsConfig;
import com.mzj.saas.constant.WxConstant;
import com.mzj.saas.manager.AsyncManager;
import com.mzj.saas.mservice.property.repository.MatchUserHouseRepository;
import com.mzj.saas.mservice.sms.service.SmsService;
import com.mzj.saas.mservice.sys.entity.WechatAccount;
import com.mzj.saas.mservice.sys.repository.WechatAccountRepository;
import com.mzj.saas.redis.RedisService;
import com.mzj.saas.util.LoginUserUtil;
import com.mzj.saas.util.UniAppUtil;
import jodd.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 订单Controller
 *
 * @author haixiaoke
 * @date 2023-04-12
 */
@RestController
@RequestMapping("/biz/order")
public class OrderController extends BaseController {
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IOrderOperatingRecordService iOrderOperatingRecordService;
    @Autowired
    private IOrderLockService iOrderLockService;
    @Autowired
    private IOrderAmountItemService iOrderAmountItemService;
    @Autowired
    private IHousingAllocationService iHousingAllocationService;
    @Autowired
    private ICalendarPriceService iCalendarPriceService;
    @Autowired
    private IPayTypeService iPayTypeService;
    @Autowired
    private IUserService iUserService;
    @Autowired
    private IOrderContractService iOrderContractService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WechatAccountRepository wechatAccountRepository;
    @Autowired
    private MatchUserHouseRepository matchUserHouseRepository;
    @Autowired
    private ICommunityHouseUserService communityHouseUserService;

    @Autowired
    private LoginUserUtil loginUserUtil;
    @Autowired
    private PayConfig payConfig;
    @Autowired
    private WxConstant wxConstant;

    @Autowired
    private SmsConfig smsConfig;
    @Autowired
    private SmsService smsService;


    /**
     * 根据企业id查询订单列表
     */
    @CheckAuth
    @GetMapping("/listByOrgId")
    public TableDataInfo list(Order order) {
        order.setOrgId(loginUserUtil.getOrgId());
        startPage();
        List<Order> list = orderService.selectOrderList(order);
        return getDataTable(list);
    }

    /**
     * 根据企业id查询订单列表
     */
    @CheckAuth
    @GetMapping("/listByHouse")
    public TableDataInfo listByHouse(Order order) {
        order.setOrgId(loginUserUtil.getOrgId());
        order.setOrderStateList(new int[]{3,4,5});
        startPage();
        List<Order> list = orderService.selectOrderListByHouse(order);
        return getDataTable(list);
    }

    /**
     * 根据小程序的用户id查询订单列表
     */
    @CheckAuth
    @GetMapping("/listByUserId")
    public TableDataInfo listByUserId(Order order) {
        String id = loginUserUtil.getId();
        order.setReservationId(id);
        startPage();
        List<Order> list = orderService.selectOrderList(order);
        return getDataTable(list);
    }

    @CheckAuth
    @GetMapping("/listByUserId/validOrder")
    public TableDataInfo listByUserIdValid(Order order) {
        String id = loginUserUtil.getId();
        String phone = loginUserUtil.getPhone();
        order.setReservationId(id);
        order.setReservationPhone(phone);
        startPage();
        List<Order> list = orderService.selectOrderListValid(order);
        return getDataTable(list);
    }

    @GetMapping("/orderInfo/{orderId}")
    @CheckAuth
    public AjaxResult orderInfo(@PathVariable("orderId") String orderId){
        return success(orderService.orderInfo(orderId));
    }

    /**
     * 获取订单详细信息
     */
    @CheckAuth
    @GetMapping(value = "/{orderId}")
    public AjaxResult getInfo(@PathVariable("orderId") String orderId) {
        return success(orderService.selectOrderDetailsByOrderId(orderId));
    }

    /**
     * 修改订单
     */
    @CheckAuth
    @PutMapping
    @RepeatSubmit
    public AjaxResult edit(@RequestBody Order order) {
        return toAjax(orderService.updateOrder(order));
    }

    /**
     * 返回订单预订的房屋基本信息
     */
    @CheckAuth
    @GetMapping("/confirm/{houseId}")
    public AjaxResult confirm(@PathVariable("houseId") String houseId) {
        HouseAndAllocationDTO houseAndAllocationDTO = null;
        if (StringUtils.isNotEmpty(houseId)) {
            //查询订单所选的房屋及房屋配置信息
            houseAndAllocationDTO = orderService.selectHouseAndAllocation(houseId);
            if (houseAndAllocationDTO != null) {

                TokenRedisVo tokenVo = loginUserUtil.getTokenRedis();
                if (ObjectUtil.isNotEmpty(houseAndAllocationDTO)) houseAndAllocationDTO.setTokenRedisVo(tokenVo);
                //设置过期时间 10分钟
                redisTemplate.opsForValue().set(Order.REDIS_ORDER_KEY + houseAndAllocationDTO.getCacheKey(), houseAndAllocationDTO, 10, TimeUnit.MINUTES);
                List<OrderLock> lockList = iOrderLockService.selectOrderLockListByHouseId(houseId, DateUtil.date());
                houseAndAllocationDTO.setOrderLockList(lockList);
                houseAndAllocationDTO.setHouseFacilitiesItemList(null);
                houseAndAllocationDTO.setCalendarPriceList(null);
                houseAndAllocationDTO.setPayType(null);
            }
        }
        if (houseAndAllocationDTO == null) {
            return error("获取信息失败");
        } else {
            return success(houseAndAllocationDTO);
        }
    }

    /**
     * 检测订单并统计金额
     *
     * @param orderDTO
     * @return
     */
    @CheckAuth
//    @RepeatSubmit
    @PostMapping("/computed")
    public AjaxResult computed(@RequestBody OrderDTO orderDTO) {
        HouseAndAllocationDTO dto = orderService.parseHouseMsg(Order.REDIS_ORDER_KEY + orderDTO.getCacheKey());
        if (ObjectUtil.isEmpty(dto)) {
            return error("订单超时，请重新确认信息");
        }
        Boolean result = orderService.checkOrderState(orderDTO.getCacheKey());
        if (!result) {
            return error("该订单已支付");
        }
        OrderAmountVO vo = orderService.computedAmount(dto.getCalendarPriceList(), dto.getPayType(), dto.getHousingAllocation(), orderDTO, true);
        if (vo == null) {
            return error("金额统计失败");
        }
        for (OrderAmountItem x : vo.getOrderAmountItemList()) {
            if (OrderAmountItem.GOODS_TYPE_HOUSE.equals(x.getGoodsType()) && StrUtil.isNotEmpty(x.getAmountDetail())) {
                List<AmountDetailDTO> detailDTOList = GsonUtil.toBeanCollectors(x.getAmountDetail(), new TypeToken<List<AmountDetailDTO>>() {
                }.getType());
                x.setAmountDetailDTOList(detailDTOList);
            }
        }

        return success(vo);
    }

    @CheckAuth
    @PostMapping("/reletComputed")
    public AjaxResult reletComputed(@RequestBody OrderDTO orderDTO) {
        Order order = orderService.selectOrderById(orderDTO.getCacheKey());
        HousingAllocation oldHousingAllocation = GsonUtil.toBean(order.getAllocationContent(), HousingAllocation.class);
        HousingAllocation housingAllocation = iHousingAllocationService.selectHousingAllocationByAllocationId(order.getAllocationId());
        if (Order.CLEANING_TYPE_NO.equals(order.getCleaningType()) && Order.CLEANING_TYPE_YES.equals(orderDTO.getCleaningType())) {
            housingAllocation.setCleaningPrice(oldHousingAllocation.getCleaningPrice());
        }
        //订单已经购买保洁费的话，不许重复购买保洁费
        if (Order.CLEANING_TYPE_YES.equals(order.getCleaningType()) && Order.CLEANING_TYPE_YES.equals(orderDTO.getCleaningType())) {
            orderDTO.setCleaningType(Order.CLEANING_TYPE_YES);
        }
        orderDTO.setCheckInTime(order.getCheckOutTime());
        List<CalendarPrice> calendarPriceList = null;
        PayType payType = null;
        if (HousingAllocation.APARTMENT_TYPE_SHORT.equals(housingAllocation.getApartmentType())) {
            calendarPriceList = iCalendarPriceService.selectCalendarPriceByHouseId(order.getHouseId());
        } else if (HousingAllocation.APARTMENT_TYPE_LONG.equals(housingAllocation.getApartmentType())) {
            payType = iPayTypeService.selectPayTypeById(housingAllocation.getPayTypeId());
        }
        OrderAmountVO vo = orderService.computedAmount(calendarPriceList, payType, housingAllocation, orderDTO, false);
        if (vo == null) {
            return error("金额统计失败");
        }

        for (OrderAmountItem x : vo.getOrderAmountItemList()) {
            if (OrderAmountItem.GOODS_TYPE_RE_LET.equals(x.getGoodsType()) && StrUtil.isNotEmpty(x.getAmountDetail())) {
                List<AmountDetailDTO> detailDTOList = GsonUtil.toBeanCollectors(x.getAmountDetail(), new TypeToken<List<AmountDetailDTO>>() {
                }.getType());
                x.setAmountDetailDTOList(detailDTOList);
            }
        }
        return success(vo);
    }

    @CheckAuth
    @RepeatSubmit
    @PostMapping("/createOrder")
    @Transactional
    public AjaxResult createOrder(@RequestBody OrderDTO orderDTO) {

        HouseAndAllocationDTO dto = orderService.parseHouseMsg(Order.REDIS_ORDER_KEY + orderDTO.getCacheKey());
        if (ObjectUtil.isEmpty(dto)) {
            return error("订单超时，请重新确认信息");
        }

        if (!HousingAllocation.APARTMENT_STATE_UP.equals(dto.getHousingAllocation().getApartmentState())) {
            return error("房屋信息配置异常");
        }

        //判断入住时间天数是否大于等于可房屋配置最小起租天数
        long day = DateUtil.between(orderDTO.getCheckInTime(), orderDTO.getCheckOutTime(), DateUnit.DAY);
        if (day < dto.getHousingAllocation().getRentStartingTime()) {
            return error("租赁的天数达不到房屋的最小起租时间");
        }

        if (HousingAllocation.APARTMENT_TYPE_LONG.equals(dto.getHousingAllocation().getApartmentType()) && dto.getHousingAllocation().getRentStartingTime() < 90) {
            return error("公寓租赁时间配置异常，请联系客服！");
        }

        //判断是否在房屋配置起租时间范围内起租
        Boolean timeResult = orderService.checkTimeValid(orderDTO.getCheckInTime(), orderDTO.getCheckOutTime(), dto.getHousingAllocation().getRentableStartTime(), dto.getHousingAllocation().getRentableEndTime());
        if (!timeResult) {
            return error("选择的时间段不在房间可租赁时间段内");
        }

        //锁单校验
        Boolean checkResult = iOrderLockService.checkHouseLock(orderDTO.getCheckInTime(), orderDTO.getCheckOutTime(), dto.getHouse().getId(), null, true);
        if (checkResult) return error("所选时间内，房屋不能出租，请重新选择入住时间");

        Boolean result = orderService.checkOrderState(orderDTO.getCacheKey());
        if (!result) {
            return error("该订单已支付");
        }
        Order order = orderService.createOrder(orderDTO, dto);
        if (ObjectUtil.isEmpty(order)) {
            return error("订单创建失败");
        }
        //消息推送
//        List<AppUser> appUserList = iAppUserService.selectMobileDevicesIdByOrgId(order.getOrgId());
        List<User> appUserList = iUserService.selectMobileDevicesIdByOrgId(order.getOrgId());
        appUserList = appUserList.stream().filter(Objects::nonNull).collect(Collectors.toList());
        List<String> mobileDevicesList = appUserList.stream().map(User::getMobileDevicesId).filter(Objects::nonNull).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(mobileDevicesList)) {
            List<User> collect = appUserList.stream().filter(x -> StringUtil.isNotEmpty(x.getMobileDevicesId())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(collect)) {
                for (User appUser : collect) {
                    Object o = redisTemplate.opsForValue().get(UniAppUtil.UNI_APP_ORDER_KEY + appUser.getId());
                    String orderStr;
                    if (ObjectUtil.isNotEmpty(o)) {
                        orderStr = o + "," + order.getOrderId();
                    } else {
                        orderStr = order.getOrderId();
                    }
                    redisTemplate.opsForValue().set(UniAppUtil.UNI_APP_ORDER_KEY + appUser.getId(),orderStr);
                }
            }
            //异步处理回调业务
            AsyncManager.me().execute(new TimerTask() {
                @Override
                public void run() {
                    UniAppUtil.sendMessage("房管家通知", "您有新的订单", order.getOrderId(), mobileDevicesList);
                }
            });
        }
        this.packagingOrderDTO(orderDTO, dto.getHouse().getOrgId(), wxConstant.wxPayApartmentCallbackUrl);
        //微信支付
        Map<String, Object> resultMap = orderService.orderWxPay(orderDTO, dto, order);
        if (CollectionUtil.isNotEmpty(resultMap)) {
            //删除缓存订单数据
            redisTemplate.delete(Order.REDIS_ORDER_KEY + orderDTO.getCacheKey());
        }
        return success(resultMap);
    }

    @GetMapping("/reletCheckTime")
    public AjaxResult reletCheckTime(String orderId) {
        Order order = orderService.selectOrderById(orderId);
        if (ObjectUtil.isEmpty(order)) return error("订单查询不到!");
        HousingAllocation housingAllocation = iHousingAllocationService.selectHousingAllocationById(order.getAllocationId());
        Date date = null;
        if (HousingAllocation.APARTMENT_TYPE_SHORT.equals(housingAllocation.getApartmentType())) {
            date = DateUtils.addDays(order.getCheckOutTime(), 1);
        } else if (HousingAllocation.APARTMENT_TYPE_LONG.equals(housingAllocation.getApartmentType())) {
            date = DateUtils.addDays(order.getCheckOutTime(), 30);
        }
        Boolean result = iOrderLockService.checkHouseLock(order.getCheckInTime(), date, order.getHouseId(), order.getOrderId(), true);
        if (result) return error("当前订单已不能续租");
        return success();
    }

    @CheckAuth
    @RepeatSubmit
    @PostMapping("/reletOrder")
    @Transactional
    public AjaxResult reletOrder(@RequestBody OrderDTO orderDTO) {

        //设置续租订单的入住时间--源头订单有房屋配置的快照数据
        Order order = orderService.selectOrderById(orderDTO.getCacheKey());
        if (!(Order.ORDER_STATE_CHECK_IN.equals(order.getOrderState()) || Order.ORDER_STATE_UN_INSPECTION.equals(order.getOrderState()) ||
                Order.ORDER_STATE_INSPECTION.equals(order.getOrderState()))) {
            return error("该订单已不可续租");
        }
        orderDTO.setCheckInTime(order.getCheckOutTime());
        //锁单校验
        Boolean checkResult = iOrderLockService.checkHouseLock(orderDTO.getCheckInTime(), orderDTO.getCheckOutTime(), order.getHouseId(), order.getOrderId(), false);
        if (checkResult) return error("所选时间内，房屋不能出租，请重新选择入住时间");

        //新的房屋配置
        HousingAllocation housingAllocation = iHousingAllocationService.selectHousingAllocationByAllocationId(order.getAllocationId());

        if (HousingAllocation.APARTMENT_TYPE_LONG.equals(housingAllocation.getApartmentType()) && housingAllocation.getRentStartingTime() < 90) {
            return error("公寓租赁时间配置异常，请联系客服！");
        }

        if (!HousingAllocation.APARTMENT_STATE_UP.equals(housingAllocation.getApartmentState())) {
            return error("房屋信息配置异常");
        }

        //判断是否在房屋配置起租时间范围内起租
        Boolean timeResult = orderService.checkTimeValid(orderDTO.getCheckInTime(), orderDTO.getCheckOutTime(), housingAllocation.getRentableStartTime(), housingAllocation.getRentableEndTime());
        if (!timeResult) {
            return error("选择的时间段不在房间可租赁时间段内");
        }

        String id = loginUserUtil.getId();
        orderDTO.setUpdateBy(id);

        order.setReletNum(order.getReletNum() + 1);
        //续租订单id    续租订单调起支付需要拼接“_”和续租次数，给微信支付传商户订单号
        String reletOrderId = order.getOrderId() + "_" + order.getReletNum();
        orderDTO.setCacheKey(reletOrderId);

        OrderAmountVO amountVO = orderService.reletOrder(orderDTO, order, housingAllocation);
        if (ObjectUtil.isEmpty(amountVO)) {
            return error("订单续租失败");
        }
        this.packagingOrderDTO(orderDTO, order.getOrgId(), wxConstant.wxReLetApartmentCallbackUrl);
        Map<String, Object> result = orderService.reletOrderWxPay(orderDTO, order);

        if (MapUtil.isNotEmpty(result)) {
            List<OrderContract> orderContracts = iOrderContractService.selectOrderContractByOrderId(order.getOrderId());
            OrderContract orderContract = orderContracts.get(0);
            String template = orderContract.getContentTemplate();
            // 模板填充内容
            ContractParameter contractParameter = buildContractParameter(order, orderDTO, amountVO);
            Map<String, Object> map = BeanUtil.beanToMap(contractParameter);
            String content = PlaceholderUtil.format(template, map);
            OrderContract newContract = OrderContract.builder().
                    orderId(order.getOrderId()).orgId(order.getOrgId())
                    .userId(order.getReservationId()).content(content).signTime(DateUtil.date())
                    .checkInTime(orderDTO.getCheckInTime()).checkOutTime(orderDTO.getCheckOutTime())
                    .contentTemplate(template).signImg(orderContract.getSignImg()).status(OrderContract.CONTRACT_STATUS_YES).build();
            iOrderContractService.insertOrderContract(newContract);
            matchUserHouseRepository.updateMatchEndTimeByHouseId(orderDTO.getCheckOutTime(), order.getHouseId());
        }
        return success(result);
    }

    @CheckAuth
    private ContractParameter buildContractParameter(Order order, OrderDTO orderDTO, OrderAmountVO amountVO) {
        // 全地址
        String fullAddress = order.getFullAddress();
        // 甲方
        String houseOwnerName = order.getHouseOwnerName();
        String houseOwnerPhone = order.getHouseOwnerPhone();

        // 乙方
        String reservationName = order.getReservationName();
        String reservationPhone = order.getReservationPhone();
        String idCardNumber = order.getReservationCardNumber();

        // 租赁期限
        Date checkInTime = orderDTO.getCheckInTime();
        Date checkOutTime = orderDTO.getCheckOutTime();
        String timeRange = DateUtil.format(checkInTime, "yyyy-MM-dd") + " ~ " + DateUtil.format(checkOutTime, "yyyy-MM-dd");

        // 租金
        String priceAmounts = Convert.toStr(amountVO.getAmount());

        // 押金
        // biz_order_amount_item  goods_type(1:房屋价格；2:保洁费；3:押金；)
        //Double deposit = iOrderAmountItemService.selectDepositByOrderId(order.getOrderId());

        // 面积
        String area = Convert.toStr(order.getArea());

        // 房型
        String houseType = order.getHouseType();

        // 合同签订日期
        String day = DateUtil.today();

        return ContractParameter.builder().address(fullAddress)
                .timeRange(timeRange).partyAName(houseOwnerName)
                .partyAContact(houseOwnerPhone)
                .partyBName(reservationName)
                .partyBContact(reservationPhone)
                .partyBIdNumber(idCardNumber)
                .deposit(Convert.toStr(0))
                .area(area).houseType(houseType)
                .day(day)
                .rentAmount(priceAmounts)
                .build();
    }

    /**
     * 未订单再次支付
     *
     * @param orderDTO
     * @return
     */
    @CheckAuth
    @RepeatSubmit
    @PostMapping("/orderPay")
    public AjaxResult orderPay(@RequestBody OrderDTO orderDTO) {
        Order order = orderService.selectOrderById(orderDTO.getCacheKey());
        //只有未支付订单能支付
        if (!Order.ORDER_STATE_UN_PAYMENT.equals(order.getOrderState())) return error("该订单已支付");
        this.packagingOrderDTO(orderDTO, order.getOrgId(), wxConstant.wxPayApartmentCallbackUrl);
        Map<String, Object> result = orderService.orderRePay(order, orderDTO);
        return success(result);
    }

    public void packagingOrderDTO(OrderDTO orderDTO, Long orgId, String wxNotifyUrl) {
        WechatAccount account = wechatAccountRepository.findByOrgIdAndType(orgId, PaymentTypeEnum.WECHAT.getValue());
        String ip = redisService.getValue(Constant.SPBILL_CREATE_IP);
        if (ObjectUtil.isEmpty(account)) {
            throw new BizException(Integer.valueOf(StatusCode.ERROR_CODE_10030.getErrorCode()), StatusCode.ERROR_CODE_10030.getErrorMsg());
        }
        orderDTO.setAppId(wxConstant.wxApartmentAppid);
        orderDTO.setMchId(account.getMchId());
        orderDTO.setMchApiKey(account.getMchApiKey());
        orderDTO.setOpenId(orderDTO.getOpenId());
        orderDTO.setSpbillCreateIp(ip);
        orderDTO.setWxNotifyUrl(wxNotifyUrl);
        orderDTO.setUnifiedApi(payConfig.getUnifiedApi());
    }

    @CheckAuth
    @GetMapping("/orderByUserId/{userId}")
    public AjaxResult orderByHouseId(@PathVariable("userId") String userId) {
        List<Order> orders = orderService.selectOrderByReservationId(userId);
        return success(orders);
    }

    //修改订单状态为入住
    @CheckAuth
    @RepeatSubmit
    @PutMapping("/updateOrderCheckIn/{orderId}")
    public AjaxResult updateOrderCheckIn(@PathVariable("orderId") String orderId) {
        Order order = orderService.selectOrderById(orderId);
        int i = 0;
        if (Order.ORDER_STATE_PAYMENT.equals(order.getOrderState())) {
            String id = loginUserUtil.getId();
            order.setUpdateBy(id);
            order.setUpdateTime(new Date());
            order.setOrderState(Order.ORDER_STATE_CHECK_IN);
            i = orderService.updateOrderState(order);
        }
        return toAjax(i);
    }

    //修改订单状态为已取消
    @CheckAuth
    @RepeatSubmit
    @PostMapping("/updateOrderCancel")
    public AjaxResult updateOrderCancel(@RequestBody OrderOperatingRecord record) {
        Order order = orderService.selectOrderById(record.getOrderId());
        int i;
        //订单状态只有未支付可以变成已取消
        if (Order.ORDER_STATE_UN_PAYMENT.equals(order.getOrderState())) {
            Date createTime = new Date();
            String id = loginUserUtil.getId();
            Integer loginType = loginUserUtil.getLoginType();
            order.setUpdateBy(id);
            order.setUpdateTime(createTime);
            Integer sourceState = order.getOrderState();
            order.setOrderState(Order.ORDER_STATE_CANCELED);
            i = orderService.updateOrderState(order);
            record.setOrderId(order.getOrderId());      //订单id
            record.setOrderSourceState(sourceState);
            record.setOrderState(Order.ORDER_STATE_CANCELED); //订单状态
            record.setOperatingBy(id);    //操作人id
            record.setOperatingTime(createTime);//操作时间
            record.setUserType(loginType == 1 ? loginType : 2);
            if (StringUtil.isEmpty(record.getRemark()) && !OrderOperatingRecord.OPERATING_TYPE_MANUAL.equals(record.getOperatingType())) {
                record.setRemark(OrderOperatingRecord.RECORD_REMARK_USER_CANCELED);//备注内容
            }
            //添加订单操作记录
            iOrderOperatingRecordService.insertOrderOperatingRecord(record);
            iOrderLockService.deleteOrderLockByOrderId(record.getOrderId());
        } else {
            throw new BizException(Integer.valueOf(StatusCode.ORDER_UPDATE_ERROR_60001.getErrorCode()), StatusCode.ORDER_UPDATE_ERROR_60001.getErrorMsg());
        }
        return toAjax(i);
    }

    @CheckAuth
    @PostMapping("/orderRefund")
    @Transactional
    @RepeatSubmit
    public AjaxResult orderRefund(@RequestBody OrderOperatingRecord record) {
        Order order = orderService.selectOrderById(record.getOrderId());
        if (ObjectUtil.isEmpty(order)) {
            return error("订单不存在");
        }
        //只有已支付订单能退款
        if (Order.ORDER_STATE_PAYMENT.equals(order.getOrderState())) {
            Date nowTime = DateUtil.date();
            Double refundAmount = order.getPriceAmounts();
            //入住时间在当前时间之前
            if (order.getCheckInTime().before(nowTime)) {
                HousingAllocation housingAllocation = GsonUtil.toBean(order.getAllocationContent(), HousingAllocation.class);
                Double cashPledge = 0d;
                if (HousingAllocation.APARTMENT_TYPE_SHORT.equals(housingAllocation.getApartmentType())) {
                    cashPledge = housingAllocation.getCashPledge();
                } else if (HousingAllocation.APARTMENT_TYPE_LONG.equals(housingAllocation.getApartmentType())) {
                    OrderAmountItem orderAmountItem = iOrderAmountItemService.selectOrderAmountItemByOrderIdAndGoodsType(order.getOrderId(), OrderAmountItem.GOODS_TYPE_CASHPLEDGE);
                    cashPledge = orderAmountItem.getItemSum();
                }
                refundAmount = BigDecimal.valueOf(refundAmount).subtract(BigDecimal.valueOf(cashPledge)).doubleValue();
            }
            WechatAccount account = wechatAccountRepository.findByOrgIdAndType(order.getOrgId(), PaymentTypeEnum.WECHAT.getValue());
            OrderWxRefundDTO refund = new OrderWxRefundDTO(order.getOrderId(), wxConstant.wxApartmentAppid, account.getMchId(),
                    account.getMchApiKey(), account.getMchCertificate(), wxConstant.wxRefundApartmentCallbackUrl, wxConstant.wxRefundUrl, order.getPriceAmounts(), refundAmount);
            Map<String, String> result = orderService.orderRefund(refund);
            if (CollectionUtil.isNotEmpty(result) && "SUCCESS".equals(result.get("result_code"))) {
                String id = loginUserUtil.getId();
                order.setUpdateBy(id);
                order.setUpdateTime(nowTime);
                order.setRefundAmounts(refundAmount);
                Integer sourceState = order.getOrderState();
                order.setOrderState(Order.ORDER_STATE_UN_REFUND);
                orderService.updateOrderState(order);
                record.setOrderId(order.getOrderId());      //订单id
                record.setOrderSourceState(sourceState);
                record.setOrderState(Order.ORDER_STATE_UN_REFUND); //订单状态
                record.setOperatingBy(id);    //操作人id
                record.setOperatingTime(nowTime);                //操作时间
                if (StringUtil.isEmpty(record.getRemark()) && !OrderOperatingRecord.OPERATING_TYPE_MANUAL.equals(record.getOperatingType())) {
                    record.setRemark(OrderOperatingRecord.RECORD_REMARK_BEING_REFUNDED);//备注内容
                }
                //添加订单操作记录
                iOrderOperatingRecordService.insertOrderOperatingRecord(record);
                //删除订单锁单表
                iOrderLockService.deleteOrderLockByOrderId(record.getOrderId());
                //标记收费项目为已退款
                OrderAmountItem item = new OrderAmountItem();
                item.setOrderId(order.getOrderId());
                item.setRefundType(OrderAmountItem.GOODS_REFUND_YES);
                item.setUpdateBy(id);
                item.setUpdateTime(nowTime);
                iOrderAmountItemService.updateOrderAmountItemByOrderId(item);

                //订单退款人跟订单预约人不同的话，则发送短信
                if (!order.getReservationId().equals(id)) {
                    smsService.sendTemplateSmsWithData(order.getReservationPhone(),smsConfig.getApartmentOrderTemplateCode(),new String[]{order.getOrderId()});
                }
                return success(result);
            }
            return error("订单退款失败");
        } else {
            throw new BizException(Integer.valueOf(StatusCode.ORDER_UPDATE_ERROR_60001.getErrorCode()), StatusCode.ORDER_UPDATE_ERROR_60001.getErrorMsg());
        }
    }

    @CheckAuth
    @RepeatSubmit
    @PostMapping("/orderRebates")
    @Transactional
    public AjaxResult orderRebates(@RequestBody OrderCheckOutDTO orderCheckOutDTO) {
        if (orderCheckOutDTO.getRefundNum() == null || orderCheckOutDTO.getRefundNum() < 0
                || orderCheckOutDTO.getActualRefundNum() == null || orderCheckOutDTO.getActualRefundNum() < 0)
            return error("金额异常");
        Order order = orderService.selectOrderById(orderCheckOutDTO.getOrderId());
        Date nowTime = DateUtil.date();
        OrderAmountItem cleaningItem = null;
        if (ObjectUtil.isEmpty(order)) {
            return error("订单获取异常");
        } else {
            if (Order.ORDER_STATE_CHECK_OUT.equals(order.getOrderState())) {

                if (Order.CLEANING_TYPE_YES.equals(order.getCleaningType()) && Order.CLEANING_TYPE_YES.equals(orderCheckOutDTO.getCleaningType())) {
                    return error("订单已购买保洁费，无需重新购买！");
                }

                //如果要购买保洁费，则加上保洁费金额
                if (Order.CLEANING_TYPE_NO.equals(order.getCleaningType()) && Order.CLEANING_TYPE_YES.equals(orderCheckOutDTO.getCleaningType())) {
                    HousingAllocation housingAllocation = iHousingAllocationService.selectHousingAllocationById(order.getAllocationId());
                    if (ObjectUtil.isNotEmpty(housingAllocation)) {
                        BigDecimal refundNum = BigDecimal.valueOf(orderCheckOutDTO.getRefundNum());
                        BigDecimal actualRefundNum = BigDecimal.valueOf(orderCheckOutDTO.getActualRefundNum());
                        refundNum = refundNum.add(BigDecimal.valueOf(housingAllocation.getCleaningPrice()));
                        actualRefundNum = actualRefundNum.add(BigDecimal.valueOf(housingAllocation.getCleaningPrice()));
                        orderCheckOutDTO.setRefundNum(refundNum.doubleValue());
                        orderCheckOutDTO.setActualRefundNum(actualRefundNum.doubleValue());

                        cleaningItem = new OrderAmountItem(null, order.getOrderId(), null, housingAllocation.getCleaningPrice(),
                                (double) 1, housingAllocation.getCleaningPrice(), OrderAmountItem.GOODS_TYPE_CLEANING, null, null, 30L);
                    }
                }


                if (order.getPriceAmounts() < orderCheckOutDTO.getActualRefundNum()) {
                    return error("退款金额不能大于订单总金额！");
                }

                WechatAccount account = wechatAccountRepository.findByOrgIdAndType(order.getOrgId(), PaymentTypeEnum.WECHAT.getValue());
                OrderWxRefundDTO refund = new OrderWxRefundDTO(null, wxConstant.wxApartmentAppid, account.getMchId(),
                        account.getMchApiKey(), account.getMchCertificate(), wxConstant.wxRefundApartmentCallbackUrl, wxConstant.wxRefundUrl, null, null);
                orderCheckOutDTO.setUserId(loginUserUtil.getId());
                Integer orderState;
                if (orderCheckOutDTO.getActualRefundNum() >0) {
                    orderService.orderRebates(order, refund, orderCheckOutDTO);
                    //走退款业务，订单状态为待退款
                    orderState = Order.ORDER_STATE_UN_REFUND;
                } else {
                    //不走退款业务，订单状态为已完成
                    orderState = Order.ORDER_STATE_COMPLETION;
                }

                //修改订单状态
                order.setOrderState(orderState);
                order.setUpdateBy(loginUserUtil.getId());
                order.setUpdateTime(nowTime);
                orderService.updateOrderState(order);

                if (ObjectUtil.isNotEmpty(cleaningItem)) {
                    iOrderAmountItemService.insertOrderAmountItem(cleaningItem);
                }

                //记录订单操作信息
                OrderOperatingRecord record = new OrderOperatingRecord();
                record.setOrderId(order.getOrderId());      //订单id
                record.setOrderSourceState(Order.ORDER_STATE_CHECK_OUT);
                record.setOrderState(order.getOrderState()); //订单状态
                record.setOperatingBy(loginUserUtil.getId());    //操作人id
                record.setOperatingTime(nowTime);                //操作时间
                record.setRemark(OrderOperatingRecord.RECORD_REMARK_BEING_REFUNDED);//备注内容
                iOrderOperatingRecordService.insertOrderOperatingRecord(record);
                return success();
            } else {
                return error("订单状态异常");
            }
        }
    }

    /**
     * 订单部分退款信息
     *
     * @param orderId
     * @return
     */
    @CheckAuth
    @GetMapping("/checkOutInfo")
    public AjaxResult checkOutInfo(@RequestParam("orderId") String orderId) {
        if (StringUtil.isEmpty(orderId)) {
            return error("订单号为空");
        }
        return success(orderService.checkOutInfo(orderId));
    }

    /**
     * 订单部分退款后信息
     */
    @CheckAuth
    @GetMapping("/rebatesInfo")
    public AjaxResult rebatesInfo(@RequestParam("orderId") String orderId) {
        return success(orderService.rebatesInfo(orderId));
    }

    /**
     * 获取订单状态常量集合
     *
     * @return
     */
    @GetMapping("/orderStateList")
    public AjaxResult getOrderState() {
        return success(orderService.getStateList());
    }

    @CheckAuth
    @RepeatSubmit
    @PostMapping("/deleteUnRelet/{orderId}")
    @ResponseBody
    public void deleteUnRelet(@PathVariable("orderId") String orderId) {
        orderService.deleteUnRelet(orderId);
    }

    @CheckAuth
    @GetMapping("/userList")
    public TableDataInfo userList(CommunityHouseUser communityHouseUser) {
        startPage();
        List<CommunityHouseUser> list = communityHouseUserService.selectList(communityHouseUser);
        return getDataTable(list);
    }
}
